home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************/
- /* Implements frem() and rmalloc() to call memory management in SGMLMEM.C. */
- /* IDCAN eliminated (conflicts with ISO 8879 ban on re-parsing.) */
- /******************************************************************************/
- #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
- /******************************************************************************/
- /* ETDDEF: Define an element type definition.
- Use an existing one if there is one; otherwise create one, which
- rmalloc initializes to zero which shows it is a virgin etd.
- */
- PETD etddef(
- UNCH *ename) /* Element name (GI) with length byte. */
- {
- PETD p; /* Pointer to an etd. */
- int hnum; /* Hash number for ename. */
-
- if ((p = (PETD)hfind((THASH)etdtab,ename,hnum = hash(ename, ETDHASH)))==0){
- p = (PETD)hin((THASH)etdtab, ename, hnum, ETDSZ);
- }
- return p;
- }
- /******************************************************************************/
- /* ETDSET: Store data in an element type definition.
- The etd must be valid and virgin (except for adl and etdmin).
- As an etd cannot be modified, there is no checking for existing
- pointers and no freeing of their storage.
- */
- /*lint +fvr Returned value may be ignored. */
- PETD etdset(
- /*lint -fvr Restore normal LINT processing. */
- PETD p, /* Pointer to an etd. */
- UNCH fmin, /* Minimization bit flags. */
- struct thdr *cmod, /* Pointer to content model. */
- PETD *mexgrp, /* Pointers to minus and plus exception lists. */
- PETD *pexgrp, /* Pointers to minus and plus exception lists. */
- struct entity **srm) /* Short reference map. */
- {
- p->etdmin |= fmin;
- p->etdmod = cmod;
- p->etdmex = mexgrp;
- p->etdpex = pexgrp;
- p->etdsrm = srm;
- return p;
- }
- /******************************************************************************/
- /* ETDREF: Retrieve the pointer to an element type definition.
- */
- PETD etdref(
- UNCH *ename) /* Element name (GI) with length byte.. */
- {
-
- return (PETD)hfind((THASH)etdtab, ename, hash(ename, ETDHASH));
- }
- /******************************************************************************/
- /* ETDCAN: Cancel an element definition. The etd is freed and is removed
- from the hash table, but its model and other pointers are not freed.
- */
- VOID etdcan(
- UNCH *ename) /* GI name (with length and EOS). */
- {
- PETD p;
-
- if ((p = (PETD)hout((THASH)etdtab, ename, hash(ename, ETDHASH)))!=0)
- frem((UNIV)p);
- }
- /******************************************************************************/
- /* SYMBOL TABLE FUNCTIONS: These functions manage hash tables that are used
- for entities, element type definitions, IDs, and other purposes. The
- interface will be expanded in the future to include multiple environments,
- probably by creating arrays of the present hash tables with each table
- in the array corresponding to an environment level.
- */
- /******************************************************************************/
- /* HASH: Form hash value for a string.
- A simple (and probably not practical) algorithm.
- */
- int hash(
- UNCH *s, /* String to be hashed (entity name). */
- int hashsize) /* Size of hash table array. */
- {
- int hashval;
-
- for (hashval = 0; *s != EOS;) hashval += (int)*s++;
- return (hashval % hashsize);
- }
- /******************************************************************************/
- /* HFIND: Look for a name in a hash table.
- */
- struct hash *hfind(
- struct hash *htab[], /* Hash table. */
- UNCH *s, /* Entity name. */
- int h) /* Hash value for entity name. */
- {
- struct hash *np;
-
- for (np = htab[h]; np != 0; np = np->enext)
- if (strcmp(s, np->ename) == 0) return np; /* Found it. */
- return (struct hash *)0; /* Not found. */
- }
- /******************************************************************************/
- /* HIN: Locates an entry in a hash table, or allocates a new one.
- Returns a pointer to a structure containing a name
- and a pointer to the next entry. Other data in the
- structure must be maintained by the caller.
- */
- struct hash *hin(
- struct hash *htab[], /* Hash table. */
- UNCH *name, /* Entity name. */
- int h, /* Hash value for entity name. */
- UNS size) /* Size of structures pointed to by table. */
- {
- struct hash *np;
-
- if ((np = hfind(htab, name, h))!=0) return np; /* Return if name found. */
- np = (struct hash *)rmalloc(size); /* Else allocate new entry. */
- memcpy( np->ename , name, name[0] ); /* Store name in it. */
- np->enext = htab[h]; /* 1st entry is now 2nd.*/
- htab[h] = np; /* New entry is now 1st.*/
- return np; /* Return new entry ptr. */
- }
- /******************************************************************************/
- /* HOUT: Remove an entry from a hash table and return its pointer.
- The caller must free any pointers in the entry and then
- free the entry itself if that is what is desired; this
- routine does not free any storage.
- */
- /*lint +fvr Returned value may be ignored. */
- struct hash *hout(
- /*lint -fvr Restore normal LINT processing. */
- struct hash *htab[], /* Hash table. */
- UNCH *s, /* Search argument entry name. */
- int h) /* Hash value for search entry name. */
- {
- struct hash *pp, *np;
-
- for (pp = np = htab[h]; np != 0; pp = np, np = np->enext) {
- if (strcmp(s, np->ename) == 0) { /* Found it. */
- pp->enext = np->enext; /* Past entry points to next. */
- return np;
- }
- }
- return (struct hash *)0; /* NULL if not found; else ptr. */
- }
- /******************************************************************************/
- /* STRLSAVE: Save a string whose length is in its first byte.
- The string is saved with the length byte.
- */
- UNCH *strlsave(
- UNCH *s)
- {
- UNCH *rp;
-
- rp = rmalloc((UNS)*s); /* Allocate storage for string. */
- memcpy( rp , s, *s ); /* Copy string into new storage. */
- return rp; /* Return pointer to stored string. */
- }
- /******************************************************************************/
- /* REPLACE: Free the storage for the old string (p) and store the new (s).
- If the specified ptr is NULL, don't free it.
- The string is saved with the length byte and EOS.
- */
- UNCH *replace(
- UNCH *p,
- UNCH *s)
- {
- if (p) frem(p); /* Free old storage (if any). */
- if (!s) return(s); /* Return NULL if new string is NULL. */
- if ((p = rmalloc((UNS)*s))==0) { /* Allocate new uninitialized storage. */
- sgmlerr(33, (struct parse *)0, NULL, NULL);
- return NULL;
- }
- memcpy( p , s, *s ); /* Copy string into new storage. */
- return p; /* Return pointer to stored string. */
- }
- /******************************************************************************/
- /* SANDWICH: Catenate a prefix and suffix to a string.
- The prefix is placed ahead of it, the suffix after it, and
- the correct length (including length byte and EOS) of the
- catenated string into the length byte of the prefix.
- All three strings start out with length and EOS bytes.
- The pointer to the catenated string is returned.
- */
- UNCH *sandwich(
- UNCH *s, /* String, with length and EOS. */
- UNCH *pref, /* Prefix, with length and EOS. */
- UNCH *suff) /* Suffix, with length and EOS. */
- {
- UNCH *pt; /* Ptr to permanent storage for sandwich. */
- UNS sz; /* Size of sandwich, with length and EOS. */
-
- pt = rmalloc(sz = *s+*pref+*suff-4); /* Get storage for sandwich. */
- memcpy( pt+1 , pref+1, *pref-2 ); /* Move prefix 1 byte after start. */
- memcpy( pt+*pref-1 , s+1, *s-2 ); /* Move string after prefix. */
- memcpy( pt+*pref+*s-3 , suff+1, *suff-1 ); /* Move suffix after string. */
- *pt = (char)sz; /* Store size in length byte. */
- return(pt); /* Return ptr to catenated string. */
- }
- /******************************************************************************/
- /* RMALLOC: Interface to memory allocation with error handling.
- If storage is not available, fatal error message is issued.
- Storage is initialized to zeros.
- */
- UNCH *rmalloc(
- unsigned size) /* Number of bytes of initialized storage. */
- {
- im.memarea = NULL; /* Clear return data. */
- im.memsize = size; /* Size of area desired. */
- im.memtype = MEMGET; sgmlmem(&im); /* Call GET function. */
- if (im.memarea!=NULL) return im.memarea;/* If ok, return pointer. */
- /* else */ exiterr(33, (struct parse *)0);
- /*lint -unreachable There is no implied return at this point. */
- return 0; /* Avoid Borland C++ warning. */
- }
- /******************************************************************************/
- /* FREM: Free specified memory area gotten with rmalloc().
- */
- VOID frem(
- UNIV ptr) /* Memory area to be freed. */
- {
- im.memarea = ptr; /* Area to free. */
- im.memtype = MEMFREE; sgmlmem(&im); /* Call FREE function. */
- }
- /******************************************************************************/
- /* MAPSRCH: Find a string in a table and return its associated value.
- The last entry must be a dummy consisting of a NULL pointer for
- the string and whatever return code is desired if the
- string is not found in the table.
- */
- int mapsrch(
- struct map maptab[],
- UNCH *name)
- {
- int i = 0;
- UNCH *mapnm, *nm;
-
- do {
- #ifndef FINAL
- if (dtrace) tracemap(
- ((maptab==lex.s.dtb && maptab[i].mapdata<lex.s.prtmin)
- ? lex.s.pdtb[i] : maptab[i].mapnm), name, maptab[i].mapdata);
- #endif
- for (mapnm = maptab[i].mapnm, nm=name; *nm==*mapnm; mapnm++) {
- if (!*nm++) return maptab[i].mapdata;
- }
- } while (maptab[++i].mapnm);
- return maptab[i].mapdata;
- }
- /******************************************************************************/
- /* IDDEF: Define an ID control block; return -1 if it already exists.
- */
- int iddef(
- UNCH *iname, /* ID name (with length and EOS). */
- UNCH *igi) /* GI of element in which ID or REF occurred. */
- {
- PID p;
-
- p = (PID)hin((THASH)itab, iname, hash(iname, IDHASH), IDSZ);
- if (p->idl) return(-1);
- p->idl = locdef((struct loc *)0, igi);
- #ifndef FINAL
- if (itrace) traceid("IDDEF", p);
- #endif
- return(0);
- }
- /******************************************************************************/
- /* IDREF: Store a reference to an ID and define the ID if it doesn't yet exist.
- Return 1 if it existed, or 0 if newly defined.
- */
- int idref(
- UNCH *iname, /* ID name (with length and EOS). */
- UNCH *igi) /* GI of element in which ID or REF occurred. */
- {
- PID p;
- int hnum, rc;
-
- if ((p = (PID)hfind((THASH)itab, iname, (hnum = hash(iname, IDHASH))))==0){
- p = (PID)hin((THASH)itab, iname, hnum, IDSZ);
- rc = 1;
- }
- p->idrl = locdef(p->idrl, igi);
- #ifndef FINAL
- if (itrace) traceid("IDREF", p);
- #endif
- return(!rc);
- }
- /******************************************************************************/
- /* IDGET: Return 1 if an ID exists; 0 if not.
- */
- int idget(
- UNCH *iname) /* ID name (with length and EOS). */
- {
- return(hfind((THASH)itab, iname, hash(iname, IDHASH))!=0);
- }
- /******************************************************************************/
- /* LOCDEF: Create a location control block and store the current location
- in it. Return the pointer to the control block.
- */
- struct loc *locdef(
- struct loc *p, /* Ptr to location chain. */
- UNCH *igi) /* GI of element in which ID or REF occurred. */
- {
- struct loc *np;
-
- np = (struct loc *)rmalloc(LOCSZ);
- np->lnext = p; /* Next location in chain. */
- np->letdgi = igi; /* Element GI (with length and EOS). */
- np->lename = ECBPTR->ename; /* Entity name with length and EOS. */
- np->lrcnt = RCNT; /* Source record number. */
- np->lccnt = CCNT; /* Source record chars since last RS. */
- np->lfile = (ECB.estore>=ESFM) ? ECB.etx.x : 0;
- return(np);
- }
- /******************************************************************************/
- /* NTOA: Converts a positive integer (i<1000) to an ASCII string (abuf)
- in a permanent internal buffer (4 chars) whose ptr is returned.
- No leading zeros are generated.
- */
- char *ntoa(
- int i)
- {
- char *a = ntoabuf; /* Ptr to current numeral in string. */
-
- if (i>=100) { /* 3 digits only. */
- *a++ = (char)('0' + i/100); i = i%100;
- if (i>=10) {*a++ = (char)('0' + i/10); i = i%10;} /* 2nd of 3. */
- else *a++ = '0';
- }
- else if (i>=10) {*a++ = (char)('0'+i/10); i = i%10;} /* 2 digits only. */
- *a++ = (char)('0'+i); /* Last or sole digit. */
- *a = 0; /* End of string. */
- return ntoabuf;
- }
- /******************************************************************************/